#include "DirectInputFramework.h"

DirectInputFramework::DirectInputFramework()
	: m_window(0),
	m_object(0),
	m_keyboard(0),
	m_mouse(0),
	m_cursorShow(true),
	m_cursorX(0),
	m_cursorY(0),
	m_prevKey(0),
	m_prevButton(0)
{}

DirectInputFramework::~DirectInputFramework()
{
	release();
}

int DirectInputFramework::init(WindowFramework* a_window)
{
	m_window = a_window;

	if(FAILED(DirectInput8Create(
		m_window->m_wClass.hInstance,
		DIRECTINPUT_VERSION,
		IID_IDirectInput8,
		(void**)&m_object,
		0)))
		return INP_INIT_DEVICE_ERROR;

	if(FAILED(m_object->CreateDevice(
		GUID_SysKeyboard,
		&m_keyboard,
		0)))
		return INP_INIT_KDEVICE_ERROR;

	if(FAILED(m_object->CreateDevice(
		GUID_SysMouse,
		&m_mouse,
		0)))
		return INP_INIT_MDEVICE_ERROR;

	if(FAILED(m_keyboard->SetDataFormat(&c_dfDIKeyboard)))
		return INP_INIT_KFORMAT_ERROR;

	if(FAILED(m_mouse->SetDataFormat(&c_dfDIMouse)))
		return INP_INIT_MFORMAT_ERROR;

	if(FAILED(m_keyboard->SetCooperativeLevel(
		m_window->m_hWnd,DISCL_NONEXCLUSIVE|DISCL_BACKGROUND)))
		return INP_INIT_KCOOP_ERROR;

	if(FAILED(m_mouse->SetCooperativeLevel(
		m_window->m_hWnd,DISCL_NONEXCLUSIVE|DISCL_BACKGROUND)))
		return INP_INIT_MCOOP_ERROR;

	SetCursorPos(
		m_window->m_screenWidth/2,
		m_window->m_screenHeight/2);

	return INP_SUCCESS;
}

int DirectInputFramework::release()
{
	m_keyboard->Unacquire();
	m_mouse->Unacquire();

	m_prevKeys.release();
	m_prevButtons.release();

	SAFE_RELEASE_URN(m_object);

	return INP_SUCCESS;
}

int DirectInputFramework::acquire()
{
	if(FAILED(m_keyboard->Acquire()))
		return INP_UPDT_KACQUIRE_ERROR;

	if(FAILED(m_mouse->Acquire()))
		return INP_UPDT_MACQUIRE_ERROR;

	if(FAILED(m_keyboard->GetDeviceState(
		256,(LPVOID)m_keyboardState)))
		return INP_UPDT_KSTATE_ERROR;

	if(FAILED(m_mouse->GetDeviceState(
		sizeof(DIMOUSESTATE),(LPVOID)&m_mouseState)))
		return INP_UPDT_MSTATE_ERROR;

	GetCursorPos(&m_cursor);
	ScreenToClient(m_window->m_hWnd,&m_cursor);
	m_cursorX = m_cursor.x;
	m_cursorY = m_cursor.y;
	if(!m_cursorShow)
		if(m_cursorX > 0
			&& m_cursorY > 0
			&& m_cursorX <= m_window->m_windowWidth
			&& m_cursorY <= m_window->m_windowHeight)
			ShowCursor(false);
		else
			ShowCursor(true);

	if(m_cursorX < 0) m_cursorX = 0;
	if(m_cursorY < 0) m_cursorY = 0;
	if(m_cursorX >= m_window->m_windowWidth)
		m_cursorX = m_window->m_windowWidth;
	if(m_cursorY >= m_window->m_windowHeight)
		m_cursorY = m_window->m_windowHeight;
	

	return INP_SUCCESS;
}

bool DirectInputFramework::keyInput(int a_key)
{
	return (m_keyboardState[a_key] & 0x80)?true:false;
}

bool DirectInputFramework::keyPress(int a_key)
{
	if(m_keyboardState[a_key] & 0x80)
	{
		int i = 0;
		for(i = 0; i < m_prevKeys.size(); i++)
			if(a_key == m_prevKeys.get(i))
				return false;
		m_prevKeys.insertBack(a_key);
		return true;
	}
	for(int i = 0; i < m_prevKeys.size(); i++)
		if(a_key == m_prevKeys.get(i))
			m_prevKeys.remove(i);
	return false;
}

bool DirectInputFramework::anyPress()
{
	char no_keys_down[256];
	memset(no_keys_down, 0, sizeof(char)*256);

	if(memcmp(no_keys_down, m_keyboardState, 256) != 0)
		return true;
	return false;
}

bool DirectInputFramework::mouseInput(int a_button)
{
	return (m_mouseState.rgbButtons[a_button] & 0x80)?true:false;
}

bool DirectInputFramework::mousePress(int a_button)
{
	if(m_mouseState.rgbButtons[a_button] & 0x80)
	{
		int i = 0;
		for(i = 0; i < m_prevButtons.size(); i++)
			if(a_button == m_prevButtons.get(i))
				return false;
		m_prevButtons.insertBack(a_button);
		return true;
	}
	for(int i = 0; i < m_prevButtons.size(); i++)
		if(a_button == m_prevButtons.get(i))
			m_prevButtons.remove(i);
	return false;
}

void DirectInputFramework::mouseDelta(long* a_x, long* a_y, long* a_z)
{
	if(a_x) *a_x = m_mouseState.lX;
	if(a_y) *a_y = m_mouseState.lY;
	if(a_z) *a_z = m_mouseState.lZ;
}

void DirectInputFramework::mousePosition(int* a_x, int* a_y)
{
	if(a_x) *a_x = m_cursorX;
	if(a_y) *a_y = m_cursorY;
}